<?php

class Sessie {

    private $_dbVerbinding = null;
    private $_tijdstip = 0;
    private $_eindeSessie = 0;
    private $_sid = '';
    private $_ip = '';
    private $_status = [];

    public function __construct() {
        $this->_tijdstip = time();
        $this->_eindeSessie = $this->_tijdstip + intVal(Instelling::GET('sessie.duur'));
        $this->_ip = Persoon::USERIP();
        $this->_status = ['open'=>Systeem::SESSIE_STATUS_OPEN,
                          'logout'=>Systeem::SESSIE_STATUS_LOGOUT,
                          'destroy'=>Systeem::SESSIE_STATUS_DESTROY,
                          'kill'=>Systeem::SESSIE_STATUS_KILL];

        $this->_dbVerbinding = Db::GET();

        session_set_save_handler([&$this, 'sessieOpen'], [&$this, 'sessieClose'], [&$this, 'sessieRead'], [&$this, 'sessieWrite'], [&$this, 'sessieDestroy'], [&$this, 'sessieCleanUp']);

        session_start();

        $sessieVars = Instelling::GET('sessie.vars');
        foreach ($sessieVars as $sessieVar => $sessieWaarde) {
            if (!isset($_SESSION[$sessieVar])) {
                $_SESSION[$sessieVar] = $sessieWaarde;
            }
        }
    }

    public function sessieOpen($sessiePad, $sessieNaam) {
        try {
            // vraag alle sessie records op die over tijd zijn
            $dbStmt = $this->_dbVerbinding->prepare("SELECT id FROM sessie WHERE einde < :tijdstip");
            $dbStmt->bindParam(':tijdstip',$this->_tijdstip);
            $dbStmt->execute();
            if ($dbStmt->rowCount() > 0) {
                $dbRijen = implode(',',$dbStmt->fetchAll(PDO::FETCH_COLUMN,0));
                // update sessiestat
                $dbStmt = $this->_dbVerbinding->prepare("UPDATE sessiestat SET tstop=:tijdstip, status=:status WHERE id IN (:dbRijen)");
                $dbStmt->execute([':tijdstip'=>$this->_tijdstip,':status'=>$this->_status['kill'],':dbRijen'=>$dbRijen]);
                // verwijder alle sessie records die voorbij tijd zijn
                $dbStmt = $this->_dbVerbinding->prepare("DELETE FROM sessie WHERE id IN (:dbRijen)");
                $dbStmt->bindParam(':dbRijen',$dbRijen);
                $dbStmt->execute();
            }
            return true;
        } 
        catch (PDOException $ex) {

        }
    }

    public function sessieClose() {
        return true;
    }

    public function sessieRead($sessieId) {
        $this->_sid = $sessieId;
        try {
            $dbStmt = $this->_dbVerbinding->prepare("SELECT vars, id FROM sessie WHERE sid=:sid");
            $dbStmt->execute([':sid'=>$sessieId]);
            if ($dbStmt->rowCount() > 0) {
                $dbRij = $dbStmt->fetch(PDO::FETCH_ASSOC);
                $_SESSION['sessionid'] = $dbRij['id'];
                return $dbRij['vars'];
            }
            return true;
        } 
        catch (PDOException $ex) {

        }        
    }

    public function sessieWrite($sessieId, $sessieData) {
        try {
            $dbStmt = $this->_dbVerbinding->prepare("SELECT * FROM sessie WHERE sid=:sid");
            $dbStmt->execute([':sid'=>$this->_sid]);
            if ($dbStmt->rowCount() > 0) {
                // sessie bestaat
                // haal id op uit tabel sessie
                $dbStmt = $this->_dbVerbinding->prepare("SELECT id FROM sessie WHERE sid=:sid");
                $dbStmt->execute([':sid'=>$this->_sid]);
                if ($dbStmt->rowCount() == 0) {
                    die('Als je dit ziet ben je niet goed bezig...');
                }
                $dbRij = $dbStmt->fetch(PDO::FETCH_ASSOC);
                $id = $dbRij['id'];
                // update tabel sessie, schrijf sessievariabelen weg + pas tijdstip einde sessie aan
                $dbStmt = $this->_dbVerbinding->prepare("UPDATE sessie SET vars=:vars,
                                                        einde=:einde WHERE sid=:sid");
                $dbStmt->execute([':vars'=>$sessieData,
                                  ':einde'=>$this->_eindeSessie,
                                  ':sid'=>$this->_sid]);
                // update tabel sessiestat met tstop, idpersoon
                $dbStmt = $this->_dbVerbinding->prepare("UPDATE sessiestat SET
                          tstop=:tstop, 
                          idpersoon=CASE WHEN idpersoon=0 THEN :idpersoon ELSE idpersoon END
                          WHERE id=:id");
                $dbStmt->execute([':tstop'=>$this->_tijdstip,
                                  ':idpersoon'=>$_SESSION['persoonid'],
                                  ':id'=>$id]);
            }
            else {
                // sessie bestaat niet
                // maak record in tabel sessiestat aan
                $dbStmt = $this->_dbVerbinding->prepare("INSERT INTO sessiestat 
                        (tstart,idpersoon,ip,status) VALUES (:tstart,:idpersoon,:ip,:status)");
                $dbStmt->execute([':tstart'=>$this->_tijdstip,
                                  ':idpersoon'=>$_SESSION['persoonid'],
                                  ':ip'=>$this->_ip,
                                  ':status'=>$this->_status['open']]);
                // haal toegevoegde id van sessiestat op voor tabel sessie
                $id = $this->_dbVerbinding->lastInsertId();
                // record toevoegen aan tabel sessie
                $dbStmt = $this->_dbVerbinding->prepare("INSERT INTO sessie 
                        (sid,id,vars,einde) VALUES (:sid, :id, :vars, :einde)");
                $dbStmt->execute([':id'=>$id,':sid'=>$sessieId,':vars'=>$sessieData,':einde'=>$this->_eindeSessie]);
                //$dbStmt->debugDumpParams();                
            }
        } 
        catch (PDOException $ex) {

        }
    }

    public function sessieDestroy($sessieId) {
        try {
            $dbStmt = $this->_dbVerbinding->prepare("UPDATE sessiestat
                SET tstop=:tstop, status=:status
                WHERE id = (SELECT id FROM sessie
                WHERE sid=:sid)");
            $dbStmt->execute([':tstop'=>$this->_tijdstip,
                              ':status'=>$this->_status['destroy'],
                              ':sid'=>$sessieId]);
            // verwijder record in sessie
            $dbStmt = $this->_dbVerbinding->prepare("DELETE FROM sessie
                WHERE sid=:sid");
            $dbStmt->execute([':sid'=>$sessieId]);
            return true;
        } catch (Exception $ex) {

        }
    }

    public function sessieCleanUp($maxLifetime) {
        return true;
    }

}
